home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / as / dist / gdb-blocks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-01  |  7.0 KB  |  290 lines

  1. /* gdb_block.c - Deal with GDB blocks
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Implements .gdbblk, .gdbbeg, .gdbend concepts.
  22.  * No other modules need to know the details of these concepts.
  23.  *
  24.  * During assembly, note the addresses of block beginnings and ends.
  25.  * Each block has a begin-address, an end-address, a number, and
  26.  * a place in the GDB symbol file to place the 2 addresses.
  27.  * Block numbers are 0, 1, ... with no gaps.
  28.  *
  29.  * During assembly, we don't actually know the addresses, so they are
  30.  * expressed as {frag-address + offset-in-frag}.
  31.  *
  32.  * gdb_block_begin ()
  33.  *        Call once before using this package.
  34.  *
  35.  * gdb_block_beg  (number, frag, offset)
  36.  *        Note a block beginning.
  37.  *
  38.  * gdb_block_end    (number, frag, offset)
  39.  *        Note a block end.
  40.  *
  41.  * gdb_block_position (block_number, pos)
  42.  *        Remember, after assembly, to copy a structure containing
  43.  *        the beginning and ending addresses of block number
  44.  *        block_number into the gdb file, starting at position pos.
  45.  *
  46.  * gdb_block_emit  (block_number, where_in_gdb_symbol_file)
  47.  *        Emit a block begin/end locations to a place in the GDB symbol
  48.  *        file.
  49.  *
  50.  * uses:
  51.  *    xmalloc()
  52.  *    gdb_alter()
  53.  */
  54.  
  55.  
  56. #include "as.h"
  57.  
  58. /*
  59.  * malloc() calls are considered expensive. So ...
  60.  *
  61.  * We remember blocks by making a tree, and each block number has a leaf.
  62.  * The tree is 3 levels, and we don't allocate interior nodes until they
  63.  * are needed. Both leaves and interior nodes are allocated in lumps,
  64.  * which should save on malloc() calls. Due to the way we break up a
  65.  * block number to navigate through the tree, we insist that lumps of
  66.  * memory contain a power of 2 items each. Powers of 2 may differ
  67.  * for different levels of tree.
  68.  */
  69.  
  70. /*
  71.  *    A block number:
  72.  *
  73.  *    +---------------+---------------+---------------+
  74.  *    |        |        |        |
  75.  *    |  Z2-part bits    |  Z1-part bits    |  Z0-part bits    |
  76.  *    |        |        |        |
  77.  *    +---------------+---------------+---------------+
  78.  *
  79.  *    High order                Low order
  80.  *
  81.  * "Z" is short for "siZe".
  82.  */
  83.  
  84. #define LOG_2_Z0 (8)        /* How many bits are in Z0 part? */
  85. #define LOG_2_Z1 (8)        /* How many bits are in Z1 part? */
  86. #define LOG_2_Z2 (8)        /* How many bits are in Z2 part? */
  87.  
  88. #define BLOCK_NUMBER_LIMIT (1 << (LOG_2_Z0 + LOG_2_Z1 + LOG_2_Z2))
  89.                 /* What is the first block number that is */
  90.                 /* "too big"? */
  91.  
  92. struct gdb_block
  93. {
  94.   fragS *    begin_frag;
  95.   fragS *      end_frag;
  96.   long int    begin_where_in_frag;
  97.   long int      end_where_in_frag;
  98.   long int    position;    /* In GDB symbols file. */
  99. };
  100.  
  101. typedef struct gdb_block    node_0_T    [1 << LOG_2_Z0];
  102.  
  103. typedef node_0_T *        node_1_T    [1 << LOG_2_Z1];
  104.  
  105. typedef node_1_T *        node_2_T    [1 << LOG_2_Z2];
  106.  
  107.  
  108. static long int        highest_block_number_seen;
  109. static node_2_T *    root;    /* 3 level tree of block locations. */
  110.  
  111. static node_2_T * new_2 ();
  112.  
  113.  
  114. char * xmalloc();
  115. void gdb_alter();
  116.  
  117. void
  118. gdb_block_begin ()
  119. {
  120.   root = new_2 ();
  121.   highest_block_number_seen = -1;
  122. }
  123.  
  124. static node_0_T *
  125. new_0 ()
  126. {
  127.   register node_0_T *    place;
  128.  
  129.   place = (node_0_T *) xmalloc ((long)sizeof(node_0_T));
  130.   bzero ((char *)place, sizeof(node_0_T));
  131.   return (place);
  132. }
  133.  
  134. static node_1_T *
  135. new_1 ()
  136. {
  137.   register node_1_T *    place;
  138.  
  139.   place = (node_1_T *) xmalloc ((long)sizeof(node_1_T));
  140.   bzero ((char *)place, sizeof(node_1_T));
  141.   return (place);
  142. }
  143.  
  144. static node_2_T *
  145. new_2 ()
  146. {
  147.   register node_2_T *    place;
  148.  
  149.   place = (node_2_T *) xmalloc ((long)sizeof(node_2_T));
  150.   bzero ((char *)place, sizeof(node_2_T));
  151.   return (place);
  152. }
  153.  
  154. static struct gdb_block *
  155. find (block_number)
  156.      register long int    block_number;
  157. {
  158.   register node_1_T **        pp_1;
  159.   register node_0_T **        pp_0;
  160.   register struct gdb_block *    b;
  161.   register int            index0;
  162.   register int            index1;
  163.   register int            index2;
  164.  
  165. #ifdef SUSPECT
  166.   if (block_number >= BLOCK_NUMBER_LIMIT)
  167.     {
  168.       as_fatal ("gdb_block: Block number = %ld.", block_number);
  169.     }
  170. #endif
  171.  
  172.   index2 = block_number >> (LOG_2_Z0 + LOG_2_Z1);
  173.   index1 = block_number >> (LOG_2_Z0) & ((1 << LOG_2_Z1) - 1);
  174.   index0 = block_number & ((1 << LOG_2_Z0) - 1);
  175.   pp_1 = * root + index2;
  176.   if (* pp_1 == 0)
  177.     {
  178.       * pp_1 = new_1 ();
  179.     }
  180.   pp_0 = ** pp_1 + index1;
  181.   if (* pp_0 == 0)
  182.     {
  183.       * pp_0 = new_0 ();
  184.     }
  185.   b = ** pp_0 + index0;
  186.   return (b);
  187. }
  188.  
  189.  
  190. static struct gdb_block *
  191. find_create (block_number)
  192.      long int    block_number;
  193. {
  194.   if (highest_block_number_seen < block_number)
  195.     {
  196.       highest_block_number_seen = block_number;
  197.     }
  198.   return (find (block_number));
  199. }
  200.  
  201. void
  202. gdb_block_beg (block_number, frag, offset)
  203.      long int    block_number;
  204.      fragS *    frag;
  205.      long int    offset;
  206. {
  207.   struct gdb_block *    pointer;
  208.       
  209.   pointer = find_create (block_number);
  210. #ifdef SUSPECT
  211.   if (pointer -> begin_frag != 0)
  212.     {
  213.       as_warn( "Overwriting begin_frag for block # %ld.", block_number );
  214.     }
  215.   if (pointer -> begin_where_in_frag != 0)
  216.     {
  217.       as_warn( "Overwriting begin_where_in_frag for block # %ld.", block_number );
  218.     }
  219. #endif
  220.   pointer -> begin_frag      = frag;
  221.   pointer -> begin_where_in_frag = offset;
  222. }
  223.  
  224. void
  225. gdb_block_end (block_number, frag, offset)
  226.      long int    block_number;
  227.      fragS *    frag;
  228.      long int    offset;
  229. {
  230.   struct gdb_block *    pointer;
  231.       
  232.   pointer = find_create (block_number);
  233. #ifdef SUSPECT
  234.   if (pointer -> end_frag != 0)
  235.     {
  236.       as_warn( "Overwriting end_frag for block # %ld.", block_number );
  237.     }
  238.   if (pointer -> end_where_in_frag != 0)
  239.     {
  240.       as_warn( "Overwriting end_where_in_frag for block # %ld.", block_number );
  241.     }
  242. #endif
  243.   pointer -> end_frag           = frag;
  244.   pointer -> end_where_in_frag = offset;
  245. }
  246.  
  247. void
  248. gdb_block_position (block_number, pos)
  249.      long int    block_number;
  250.      long int    pos;
  251. {
  252.   struct gdb_block *    pointer;
  253.  
  254.   pointer = find_create (block_number);
  255.   if (pointer -> position != 0)
  256.     {
  257.       as_warn( "Overwriting old position %ld. in block #%ld.",
  258.           pointer -> position, block_number);
  259.     }
  260.   pointer -> position = pos;
  261. }
  262.  
  263. void
  264. gdb_block_emit ()
  265. {
  266.   long int        block_number;
  267.   struct gdb_block *    b;
  268.  
  269.   for (block_number = 0;
  270.        block_number <= highest_block_number_seen;
  271.        block_number ++)
  272.     {
  273.       b = find (block_number);
  274.       if (b -> begin_frag)
  275.     {
  276.       gdb_alter (b -> position,
  277.              (long int)
  278.              (b -> begin_frag -> fr_address + b -> begin_where_in_frag));
  279.     }
  280.       if (b -> end_frag)
  281.     {
  282.       gdb_alter (b -> position + sizeof( long int ),
  283.              (long int)
  284.              (b -> end_frag -> fr_address + b -> end_where_in_frag));
  285.     }
  286.     }
  287. }
  288.  
  289. /* end: gdb_block.c */
  290.